찾다
개발 도구자식gitee를 기반으로 파일 업로드 및 다운로드 기능을 구현하는 방법

파일 업로드 및 다운로드 기능을 어떻게 구현하나요? 다음 글에서는 gitee를 기반으로 파일 업로드 및 다운로드 기능을 구현하는 방법을 소개하겠습니다. 도움이 되셨으면 좋겠습니다!

gitee를 기반으로 파일 업로드 및 다운로드 기능을 구현하는 방법

솔루션 선택

파일 업로드 및 다운로드는 우리 프로젝트의 핵심 기능입니다. 또한 이 기능을 달성하기 위해 이전 부팅 프로젝트를 통합하고 최적화했습니다.

파일 업로드 및 다운로드에는 일반적으로 Alibaba Cloud OSS 및 Huawei Cloud OSS가 사용되며 공식에서는 그래픽 인터페이스를 제공합니다. 그러나 이러한 방법은 양에 따라 저장 비용이 필요하며 gitee와 유사합니다. 공식 인터페이스를 호출하여 구현됩니다. 학습 단계이기 때문에 gitee에 창고를 구축하고 공식 API를 사용하여 창고에 파일 업로드 및 삭제 기능을 시작하고 저장된 파일 주소를 사용하기로 결정했습니다. 브라우저 클라이언트에 파일을 다운로드하기 위한 데이터베이스입니다.

데이터베이스 테이블 디자인

기본 기능을 구현하는 데 일시적으로 두 개의 데이터베이스 테이블만 사용됩니다. 하나는 파일 테이블이고 다른 하나는 폴더 테이블입니다.

public class File {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String fileName;
    private String filePath;
    private String fileSize;

    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;

    private Long userId;
    private Long folderId;
    //分享次数
    private Integer shareTimes;
    //文件描述
    private String fileCover;
}
public class Folder {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String folderName;
    private Long fatherId;  //父文件夹id,为0表示没有最上层文件夹
    private Long userId;
    private String folderCover;
    private Boolean folderPermissions;
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;
}

gitee Warehouse 구축

먼저 자신만의 gitee를 엽니다. new A 웨어하우스 이름 입력 후 초기화 웨어하우스 확인 후 생성 후 오픈소스로 설정

gitee를 기반으로 파일 업로드 및 다운로드 기능을 구현하는 방법

웨어하우스 생성 후 "개인홈페이지" -> "개인설정" -> "비공개" 열기 토큰"은 공식 인터페이스를 호출할 때 인증을 위해 새로운 개인 토큰을 직접 생성하는 것입니다.

gitee를 기반으로 파일 업로드 및 다운로드 기능을 구현하는 방법

옵션 걱정 없이 직접 생성하세요. 토큰은 한 번만 표시되므로 저장에 주의하세요.

gitee 이미지 침대 도구 클래스 편집

다른 사람이 작성한 내용을 직접 복사하는 데 사용됩니다. 개인 토큰, 개인 공간, 창고 이름 ​​및 기본 저장 주소도 이 도구 클래스로 변경해야 합니다. 이 정보는 HttpUtil 도구 클래스를 통해 gitee 저장소에 대한 업로드 요청을 시작하는 데 사용됩니다.

package com.ityz.file.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @ClassName UploadGiteeImgBedUtil
 * @Author ityz
 * @Date 2022/11/23 16:38
 * @Description Gitee图床工具类
 */
public class GiteeImgBedUtil {


    /**
     * 码云私人令牌
     */
    private static final String ACCESS_TOKEN = "0616f0e894e3c264bac45591e34a43bc";  //这里不展示我自己的了,需要你自己补充


    /**
     * 码云个人空间名
     */
    private static final String OWNER = "procedure-yuan-yanzu";


    /**
     * 上传指定仓库
     */
    private static final String REPO = "files";


    /**
     * 默认上传时指定存放图片路径
     */
    public static final String PATH = "files/";

    //API
    /**
     * 新建(POST)、获取(GET)、删除(DELETE)文件:()中指的是使用对应的请求方式
     * %s =>仓库所属空间地址(企业、组织或个人的地址path)  (owner)
     * %s => 仓库路径(repo)
     * %s => 文件的路径(path)
     */
    private static final String API_CREATE_POST = "https://gitee.com/api/v5/repos/%s/%s/contents/%s";


    /**
     * 生成创建(获取、删除)的指定文件路径
     * @param originalFilename 原文件名
     * @param path 存储文件路径
     * @return
     */
    private static String createUploadFileUrl(String originalFilename,String path){
        String targetPath = path == null ? GiteeImgBedUtil.PATH : path;
        //获取文件后缀
        String suffix = FileUtil.getFileSuffix(originalFilename);
        //拼接存储的图片名称
        String fileName = System.currentTimeMillis()+"_"+ UUID.randomUUID().toString()+suffix;
        //填充请求路径
        String url = String.format(GiteeImgBedUtil.API_CREATE_POST,
                GiteeImgBedUtil.OWNER,
                GiteeImgBedUtil.REPO,
                targetPath + fileName);
        return url;
    }

    private static String createDelFileUrl(String path){
        //填充请求路径
        String url = String.format(GiteeImgBedUtil.API_CREATE_POST,
                GiteeImgBedUtil.OWNER,
                GiteeImgBedUtil.REPO,
                path);
        return url;
    }

    private static String createGetUrl(String path){
        String targetPath = path == null ? GiteeImgBedUtil.PATH : path;
        //填充请求路径
        String url = String.format(GiteeImgBedUtil.API_CREATE_POST,
                GiteeImgBedUtil.OWNER,
                GiteeImgBedUtil.REPO,
                targetPath);
        return url;
    }

    /**
     * 获取创建文件的请求体map集合:access_token、message、content
     * @param multipartFile 文件字节数组
     * @return 封装成map的请求体集合
     */
    private static Map<string> getUploadBodyMap(byte[] multipartFile){
        HashMap<string> bodyMap = new HashMap(3);
        bodyMap.put("access_token", GiteeImgBedUtil.ACCESS_TOKEN);
        bodyMap.put("message", "add file!");
        bodyMap.put("content", Base64.encode(multipartFile));
        return bodyMap;
    }

    /**
     * 创建普通携带请求体集合内容
     * @param map 额外参数
     * @param message 请求信息
     * @return
     */
    private static Map<string> getCommonBodyMap(HashMap map, String message){
        HashMap<string> bodyMap = new HashMap(2);
        bodyMap.put("access_token", GiteeImgBedUtil.ACCESS_TOKEN);
        bodyMap.put("message", message);
        if (map != null){
            bodyMap.putAll(map);
        }
        return bodyMap;
    }

    /**
     * **********封装好的实际调用方法*******************
     */

    //超时
    private static int TIMEOUT = 10 * 1000;

    /**
     * 上传文件
     * @param filename 文件名称
     * @param path 路径
     * @param sha 必备参数from 获取仓库具体路径下的内容
     * @return
     */
    public static String uploadFile(String path, String originalFilename, byte[] data){
        String targetURL = GiteeImgBedUtil.createUploadFileUrl(originalFilename,path);
        //请求体封装
        Map<string> uploadBodyMap = GiteeImgBedUtil.getUploadBodyMap(data);
        return HttpUtil.post(targetURL, uploadBodyMap);
    }


    /**
     * 删除指定path路径下的文件
     * @param filename 文件名称
     * @param path 路径
     * @param sha 必备参数from 获取仓库具体路径下的内容
     * @return
     */
    public static String deleteFile(String path,String sha){
        String delFileUrl = createDelFileUrl(path);
        HashMap<string> needMap = new HashMap(1);
        needMap.put("sha",sha);//添加sha参数
        return HttpUtil.createRequest(Method.DELETE, delFileUrl)
                .form(getCommonBodyMap(needMap,"del file!"))  //构建请求表单
                .timeout(TIMEOUT)
                .execute().body();
    }

    /**
     * 获取仓库具体路径下的内容,主要是获取 sha
     * @param path
     * @return
     */
    public static String getSha(String path){
        String getShaUrl = createDelFileUrl(path);
        return HttpUtil.createRequest(Method.GET, getShaUrl)
                .form(getCommonBodyMap(null, "get sha!"))
                .timeout(TIMEOUT)
                .execute().body();
    }

}</string></string></string></string></string></string>

파일 업로드 인터페이스

파일 업로드 프로세스는 파일 개체 및 관련 정보를 프런트 엔드에 전달하는 것입니다. 그런 다음 업로드가 성공한 후 gitee에 파일을 전송하라는 요청을 시작합니다. , 반환된 다운로드 주소 및 관련 정보는 데이터베이스에 저장됩니다.

중간 도구 클래스

여기서는 먼저 요청을 시작하고 결과를 얻기 위한 중간 도구 클래스를 작성합니다. 이 코드도 서비스에서 작성하면 코드가 너무 길고 복잡해 보일 수 있으므로 별도로 작성했습니다. .

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ityz.common.constants.GiteeConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

/**
 * gitee文件操作api
 */
@Slf4j
public class GiteeApi {
    /**
     * 上传文件api
     * @param multipartFile 前端传入的文件对象
     * @param folder 文件所存文件夹名称
     * @return gitee的api上传返回值的json对象
     * @throws IOException
     */
    public static JSONObject upload(MultipartFile multipartFile,String folder) throws IOException {
        log.info("uploadFile()请求已来临...");
        //根据文件名生成指定的请求url
        String originalFilename = multipartFile.getOriginalFilename();
        if (originalFilename == null) {
            log.info("服务器接收文件失败!");
        }
        //Gitee请求:发送上传文件请求
        String JSONResult = GiteeImgBedUtil.uploadFile(folder, originalFilename, multipartFile.getBytes());
        //解析响应JSON字符串
        //上传txt文件时会出问题,没解决
        JSONObject jsonObj = JSONUtil.parseObj(JSONResult);
        //请求失败
        if (jsonObj.getObj(GiteeConstant.RESULT_BODY_COMMIT) == null) {
            log.info("上传文件失败!");
        }
        //请求成功:返回下载地址
        JSONObject content = JSONUtil.parseObj(jsonObj.getObj(GiteeConstant.RESULT_BODY_CONTENT));
        log.info("上传成功,下载地址为:" + content.getStr(GiteeConstant.RESULT_BODY_DOWNLOAD_URL));
        return content;
    }
}

Controller

컨트롤러는 파일과 정보를 가져온 후 중간 도구 클래스를 호출하여 파일을 업로드한 다음 요청 헤더에서 사용자 ID를 가져오고 반환된 객체에서 파일 정보를 가져와 저장합니다. File 클래스에서 객체를 저장하기 위해 mybatisplus를 사용합니다. 데이터베이스에 저장하면 됩니다.

@RestController
@Slf4j
@RequestMapping("/file")
public class FileController {
    @Autowired
    private FileService fileService;
    @Autowired
    private HttpServletRequest request;

    /**
     * 文件上传接口
     * @param multipartFile 上传的文件对象
     * @param fileCover 文件的描述信息
     * @param folderId 文件所属的文件夹id
     * @return 用户文件地址
     * @throws IOException
     */
    @PostMapping("/upload")
    public Result<string> uploadFile(@RequestParam("file") MultipartFile multipartFile
            , @RequestParam("fileCover") String fileCover
            , @RequestParam("folderId") Long folderId) throws IOException {
        JSONObject content = GiteeApi.upload(multipartFile, "test/");
        //获取userId
        Long userId = Long.valueOf(TokenUtil.parseToken(request.getHeader("token")));
        File file = new File();
        file.setFileCover(fileCover);
        file.setUserId(userId);
        file.setFolderId(folderId);
        file.setFileName(content.getStr(GiteeConstant.RESULT_BODY_NAME));;
        file.setFileSize(content.getStr(GiteeConstant.RESULT_BODY_SIZE));
        file.setFilePath(content.getStr(GiteeConstant.RESULT_BODY_DOWNLOAD_URL));
        fileService.fileUpload(file);
        return new Result(ResultCode.SUCCESS,ResultCode.UP_FILE_SUCCESS,content.getStr(GiteeConstant.RESULT_BODY_DOWNLOAD_URL));
    }
}</string>
Ev 서비스는 Mapper를 호출하고

/**
     * 上传文件
     *
     * @param file 用于向数据库储存的文件对象
     */
    @Override
    public void fileUpload(File file) {
        file.setCreateTime(new Date());
        fileMapper.insert(file);
    }

인터페이스 테스트에 저장하는 저장 시간을 설정하는 것은 비교적 간단합니다.

파일을 업로드하여

gitee를 기반으로 파일 업로드 및 다운로드 기능을 구현하는 방법

gitee와 데이터베이스에 해당 결과가 있는지 확인합니다

gitee를 기반으로 파일 업로드 및 다운로드 기능을 구현하는 방법

gitee를 기반으로 파일 업로드 및 다운로드 기능을 구현하는 방법

이전에 데이터 조각이 삭제되었고 테이블을 처음부터 자르려고 하므로 여기서 ID는 2입니다.

파일 다운로드 인터페이스

처음에는 파일 다운로드가 귀찮았습니다. 두 가지 방법이 있습니다. 첫 번째는 사용자가 제공한 로컬 폴더 주소에 파일 개체를 직접 쓰는 것이고, 두 번째는 파일을 브라우저에 다운로드하는 것입니다. . 마지막으로 두 번째 방법을 선택한 이유는 사용자가 다운로드 주소를 설정할 필요가 없고 브라우저에서 다운로드할 때 다운로드 프로세스를 볼 수 있기 때문입니다. 전체 프로세스는 다운로드 주소를 사용하여 파일을 파일 스트림으로 변환하고 쓰는 것입니다. 이를 바이트 배열로 변환한 다음 브라우저를 사용하여 메서드를 통해 다운로드하고 바이트 배열을 출력 스트림에 씁니다.

🎜controller🎜🎜🎜 파일 ID를 사용하여 먼저 데이터베이스에서 해당 주소를 찾은 다음 이 주소를 사용하여 후속 작업을 완료합니다. 🎜
/**
     * 文件下载接口
     * @param fileId 文件id
     * @param response http响应对象
     * @return 下载结果
     */
    @GetMapping("/download")
    public Result<string> download(Long fileId,HttpServletResponse response) {
        try {
            String downloadUrl = fileService.downloadFile(fileId);
            URL url = new URL(downloadUrl);
            URLConnection conn = url.openConnection();
            InputStream bis = conn.getInputStream();
            byte[] bytes = new byte[bis.available()];
            OutputStream os = response.getOutputStream();
            // 从文件流读取字节到字节数组中
            while (bis.read(bytes) != -1) {
                // 重置 response
                response.reset();
                // 设置 response 的下载响应头
                response.setContentType("application/x-download");
                response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(FileUtil.getFileName(downloadUrl), "UTF-8"));  // 注意,这里要设置文件名的编码,否则中文的文件名下载后不显示
                // 写出字节数组到输出流
                os.write(bytes);
                // 刷新输出流
                os.flush();
            }
            return new Result(ResultCode.SUCCESS,ResultCode.DOWN_FILE_SUCCESS);
        }catch (Exception e){
            e.printStackTrace();
            return new Result(ResultCode.FAIL,ResultCode.DOWN_FILE_FAIL);
        }
    }</string>
🎜 여기에서 파일 이름을 가져오는 도구 클래스를 작성해야 합니다. 그렇지 않으면 다운로드 후 브라우저가 파일 형식을 알 수 없습니다🎜
/**
     * 获取url中的文件名(取到最后一个/后面的就是文件名)
     * @param url 文件地址
     * @return
     */
    public static String getFileName(String url) {
        if(!url.equals("")){
        return url.substring(url.lastIndexOf("/")+1);
        }
        else return "文件地址错误";
    }

接口测试 

  发送请求完成下载

gitee를 기반으로 파일 업로드 및 다운로드 기능을 구현하는 방법

文件删除接口

中间工具类

/**
     * 删除文件api
     * @param url 文件地址
     */
    public static void del(String url){
        if (!url.equals("") && !url.contains("master/")) {
            log.info("url:" + url + " 无法解析路径!");
        }
        String path = url.substring(url.indexOf("master/") + 7);
        log.info("解析取得待删除路径:" + path);
        String shaResult = GiteeImgBedUtil.getSha(path);
        JSONObject jsonObj = JSONUtil.parseObj(shaResult);
        String sha = jsonObj.getStr(GiteeConstant.RESULT_BODY_SHA);
        //3、Gitee请求:发送删除请求
        String JSONResult = GiteeImgBedUtil.deleteFile(path, sha);
        jsonObj = JSONUtil.parseObj(JSONResult);
        if (jsonObj.getObj(GiteeConstant.RESULT_BODY_COMMIT) == null) {
            log.info("删除文件失败!");
        }
        log.info("文件路径为:" + path + " 删除成功!");
    }

service

  获取文件地址并删除数据库数据

/**
     * 删除文件
     * @param fileId 文件id
     * @return
     */
    @Override
    public String delFile(Long fileId) {
        String url = fileMapper.selectById(fileId).getFilePath();
        fileMapper.deleteById(fileId);
        return url;
    }

controller

**
     * 删除文件接口
     * @param fileId 前端传入的文件id
     * @return
     */
    @GetMapping("/del")
    public Result<string> delFile(Long fileId) {
        try {
            String url = fileService.delFile(fileId);
            GiteeApi.del(url);
            return new Result(ResultCode.SUCCESS,ResultCode.DEL_FILE_SUCCESS);
        }
        catch (Exception e){
            e.printStackTrace();
            return new Result(ResultCode.FAIL,ResultCode.DEL_FILE_FAIL);
        }
    }</string>

接口测试

发送请求删除文件

gitee를 기반으로 파일 업로드 및 다운로드 기능을 구현하는 방법

 查看数据库和gitee仓库

gitee를 기반으로 파일 업로드 및 다운로드 기능을 구현하는 방법

gitee를 기반으로 파일 업로드 및 다운로드 기능을 구현하는 방법

   自此完成了文件的上传和下载功能,大家有需要的可以参考。

(学习视频分享:编程基础视频

위 내용은 gitee를 기반으로 파일 업로드 및 다운로드 기능을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
이 기사는 csdn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제
Github : 오픈 소스 및 소프트웨어 개발을위한 허브Github : 오픈 소스 및 소프트웨어 개발을위한 허브Apr 15, 2025 am 12:10 AM

GitHub는 버전 제어, 협업 개발 및 커뮤니티 커뮤니케이션 기능을 제공하는 GIT 기반 버전 제어 시스템 호스팅 플랫폼입니다. GitHub를 사용하면 개발 효율성과 코드 품질이 향상 될 수 있습니다.

Git and Github : 관계는 무엇입니까?Git and Github : 관계는 무엇입니까?Apr 14, 2025 am 12:10 AM

Git 및 Github는 다른 도구입니다. Git은 버전 제어를위한 소프트웨어이며 Github는 Git을 기반으로 한 온라인 플랫폼입니다. 1. git을 사용하면 파일 변경 및 협업 개발을 추적 할 수 있습니다. 2. GitHub은 팀 개발 효율성을 향상시키기 위해 코드 호스팅 및 협업 도구를 제공합니다.

Github : 개발자 및 프로젝트를위한 플랫폼Github : 개발자 및 프로젝트를위한 플랫폼Apr 13, 2025 am 12:01 AM

GitHub의 핵심 기능에는 버전 제어, 지점 관리, 코드 검토, 문제 추적 및 프로젝트 관리가 포함됩니다. 1. 버전 제어 및 지점 관리는 GIT를 기반으로하므로 코드 변경 및 실험 개발을 추적 할 수 있습니다. 2. 코드 검토는 PullRequest를 통해 구현되어 코드 품질 및 팀 협업을 개선합니다. 3. 문제 추적 및 프로젝트 관리는 프로젝트 투명성 및 추적 성을 향상시키기 위해 문제와 프로젝트 관리위원회를 통해 수행됩니다.

GitHub의 행동 : 예 및 사용 사례GitHub의 행동 : 예 및 사용 사례Apr 12, 2025 am 12:16 AM

Github는 소프트웨어 개발의 효율성과 품질을 향상시키는 강력한 도구입니다. 1) 버전 제어 : GIT를 통해 코드 변경을 관리합니다. 2) PullRequests : 코드 검토를 수행하고 코드 품질을 향상시킵니다. 3) 문제 : 버그 및 프로젝트 진행 상황을 추적합니다. 4) githubactions : 건설, 테스트 및 배치 프로세스를 자동화합니다.

Git vs. Github : 버전 제어 및 코드 호스팅Git vs. Github : 버전 제어 및 코드 호스팅Apr 11, 2025 am 11:33 AM

GIT는 버전 제어 시스템이며 GitHub는 GIT 기반 코드 호스팅 플랫폼입니다. GIT는 코드 버전을 관리하는 데 사용되며 로컬 작업을 지원합니다. GitHub는 문제 추적 및 풀 레크와 같은 온라인 협업 도구를 제공합니다.

간단한 말로 git은 무엇입니까?간단한 말로 git은 무엇입니까?Apr 09, 2025 am 12:12 AM

GIT는 개발자가 파일 변경을 추적하고 협력하며 코드 버전을 관리하는 데 도움이되는 오픈 소스 분산 버전 제어 시스템입니다. 핵심 기능에는 1) 레코드 코드 수정, 2) 이전 버전으로의 폴백, 3) 협업 개발 및 4) 병렬 개발을위한 분기 생성 및 관리가 포함됩니다.

git은 github와 동일합니까?git은 github와 동일합니까?Apr 08, 2025 am 12:13 AM

Git과 Github도 같은 것이 아닙니다. GIT는 버전 제어 시스템이며 GitHub는 GIT 기반 코드 호스팅 플랫폼입니다. GIT는 코드 버전을 관리하는 데 사용되며 Github은 온라인 협업 환경을 제공합니다.

HTML에 github를 사용하는 방법은 무엇입니까?HTML에 github를 사용하는 방법은 무엇입니까?Apr 07, 2025 am 12:13 AM

HTML 프로젝트를 관리하기 위해 GitHub를 사용하는 이유는 버전 제어, 협업 개발 및 작품 발표를위한 플랫폼을 제공하기 때문입니다. 특정 단계에는 다음이 포함됩니다. 1. Git 저장소 작성 및 초기화, 2. HTML 파일 추가 및 제출, 3. GitHub에 푸시, 4. GitHubPages를 사용하여 웹 페이지를 배포, 5. GitHubactions를 사용하여 빌드 및 배포를 자동화하십시오. 또한 GitHub은 HTML 프로젝트를 최적화하고 협업하는 데 도움이되는 코드 검토, 문제 및 풀 레크 기능 기능을 지원합니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
4 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
4 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
4 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
1 몇 달 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

안전한 시험 브라우저

안전한 시험 브라우저

안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.

SublimeText3 Linux 새 버전

SublimeText3 Linux 새 버전

SublimeText3 Linux 최신 버전

맨티스BT

맨티스BT

Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구