# 上传下载

我们对文件上传进行了分别封装了多个组件：

- 单图片上传（替换图片）：`src\components\pic-upload` 

- 多图片上传：`src\components\mul-pic-upload`
- 文件上传：`src\components\file-upload`  

上述这些文件上传，都是基于`el-upload`进行封装



## 单图片上传

在商品分类这个模块的弹框中可以找到单图片上传的例子，对应vue代码位置：`src\views\modules\category-add-or-update.vue` 

html:

```html
<pic-upload v-model="dataForm.pic"></pic-upload>
```

js:

```javascript
import PicUpload from '@/components/pic-upload'
export default {
  data () {
    return {
      dataForm: {
        pic: ''
      }
  },
  components: {
    PicUpload
  }
}
```

这里的文件上传使用起来非常简单，只需要将最终文件上传完成后的路径进行双向绑定即可



## 多图片上传

在商品发布这个模块的中可以找到多图片上传的例子，对应vue代码位置：`src\views\modules\category-add-or-update.vue` 

html:

```html
<mul-pic-upload v-model="dataForm.imgs" />
```

js:

```javascript
import MulPicUpload from '@/components/mul-pic-upload'
export default {
  data () {
    return {
      dataForm: {
        imgs: ''
      }
  },
  components: {
    MulPicUpload
  }
}
```

这里的文件上传使用起来也非常简单，最后返回的数据，为以逗号分隔的图片路径连接的字符串



## 服务端代码

直接的文件上传的例子与多图片上传的例子类似，这里便不一一举例了。

我们可以查看三个文件上传的源码，都有那么两句话`:action="$http.adornUrl('/admin/file/upload/element')"`  `:headers="{Authorization: $cookie.get('Authorization')}"`，其中由于规定后台所有请求都需要通过 `spring security`的授权，所以需要携带通用请求头`headers`，而`action`则是对应后台服务器的路径



我们查看后台`FileController` 这里对文件上传的接口进行了统一的管理：

```java
@RestController
@RequestMapping("/admin/file")
public class FileController {
   
   @Autowired
   private AttachFileService attachFileService;
   
   @PostMapping("/upload/element")
   public ServerResponseEntity<String> uploadElementFile(@RequestParam("file") MultipartFile file) throws IOException{
      if(file.isEmpty()){
            return ServerResponseEntity.success();
        }
      String fileName = attachFileService.uploadFile(file.getBytes(),file.getOriginalFilename());
        return ServerResponseEntity.success(fileName);
   }

   
}
```



同时我们查看`attachFileService` 的实现类，可以知道该文件上传是通过七牛云进行实现的

```java
@Service
public class AttachFileServiceImpl extends ServiceImpl<AttachFileMapper, AttachFile> implements AttachFileService {

    @Autowired
    private AttachFileMapper attachFileMapper;

    @Autowired
    private UploadManager uploadManager;

    @Autowired
    private BucketManager bucketManager;
    @Autowired
    private Qiniu qiniu;

    @Autowired
    private Auth auth;

    public final static String NORM_MONTH_PATTERN = "yyyy/MM/";

   @Override
   public String uploadFile(byte[] bytes,String originalName) throws QiniuException {
      String extName = FileUtil.extName(originalName);
      String fileName =DateUtil.format(new Date(), NORM_MONTH_PATTERN)+ IdUtil.simpleUUID() + "." + extName;


      AttachFile attachFile = new AttachFile();
      attachFile.setFilePath(fileName);
      attachFile.setFileSize(bytes.length);
      attachFile.setFileType(extName);
      attachFile.setUploadTime(new Date());
      attachFileMapper.insert(attachFile);

      String upToken = auth.uploadToken(qiniu.getBucket(),fileName);
       Response response = uploadManager.put(bytes, fileName, upToken);
       Json.parseObject(response.bodyString(),  DefaultPutRet.class);
      return fileName;
   }
}
```



在这里面注入了非常多的七牛云的配置，而配置文件的来源，来自

```java
@Configuration
public class FileUploadConfig {

   
   @Autowired
   private Qiniu qiniu;
   
    /**
     * 华南机房
     */
    @Bean
    public com.qiniu.storage.Configuration qiniuConfig() {
        return new com.qiniu.storage.Configuration(Zone.zone2());
    }

    /**
     * 构建一个七牛上传工具实例
     */
    @Bean
    public UploadManager uploadManager() {
        return new UploadManager(qiniuConfig());
    }

    /**
     * 认证信息实例
     * @return
     */
    @Bean
    public Auth auth() {
        return Auth.create(qiniu.getAccessKey(), qiniu.getSecretKey());
    }
    
    /**
     * 构建七牛空间管理实例
     */
    @Bean
    public BucketManager bucketManager() {
        return new BucketManager(auth(), qiniuConfig());
    }
}
```



## 注册七牛云账号

现在已经9102年了，很少上传文件到本地了，一般都是上传到oss，我们这里选择[七牛云存储](https://www.qiniu.com/products/kodo) ，如果没有账号的可以注册一个，创建一个华南地区的云存储空间

![img](https://box.kancloud.cn/c72238c384fb43c2c0b3161162880056_1909x545.png)

### 修改后台配置

平台端(vue)修改文件`.env.production`（生产环境）/ `.env.development`（开发环境）
里面的`VUE_APP_BASE_API`为api接口请求地址， `VUE_APP_RESOURCES_URL`为静态资源文件url 

    // api接口请求地址
    VUE_APP_BASE_API = 'http://127.0.0.1:8085'
    // 静态资源文件url
    VUE_APP_RESOURCES_URL = 'https://img.mall4j.com/'


### 更新于2023.03.27
- 在`shop.properties` 更新了本地上传的配置，vue中的`resourcesUrl`也配置对应的本地路径
- 全局搜索`/mall4j/img`，替换成你想要的图片路径，若按本代码默认的则前端的资源路径为`http://ip: + admin服务的端口号/mall4j/img/`
