Merge branch 'feature-upload-daiyb' into dev
This commit is contained in:
commit
e2abc91367
@ -1,10 +1,15 @@
|
||||
[system]
|
||||
Domain = "fiee"
|
||||
AppMode = "debug"
|
||||
Domain = "app"
|
||||
AppMode = "dev"
|
||||
HttpPort = ":8085"
|
||||
Host = "http://127.0.0.1:8085"
|
||||
Host = "https://common.szjixun.cn"
|
||||
RedirectUri = "/api/redirect/url"
|
||||
|
||||
ErpHost = "http://erpapi.test.fontree.cn:8081"
|
||||
FieeHost = "http://erpapi.test.fontree.cn:8081"
|
||||
AuthRedirectUrl = "http://saas-erp.test.fontree.cn:8081/media_account"
|
||||
AuthCallback = "https://saas-test.szjixun.cn/api/fiee/media/as-oauth2callback"
|
||||
CronOpen = true
|
||||
proxyUrl = "http://47.84.75.255:6785"
|
||||
[bos]
|
||||
Ak = "ALTAKxrqOQHnAN525Tb2GX4Bhe"
|
||||
Sk = "d2ecaa9d75114d3b9f42b99014198306"
|
||||
@ -23,7 +28,7 @@ CdnHost = "${OSS_CDN}"
|
||||
[redis]
|
||||
RedisDB = "2"
|
||||
RedisAddr = "127.0.0.1:6379"
|
||||
RedisPW = ""
|
||||
RedisPW = "7532T6R"
|
||||
RedisDBNAme = "2"
|
||||
|
||||
|
||||
|
||||
@ -2,10 +2,27 @@ dubbo:
|
||||
registries:
|
||||
demoZK:
|
||||
protocol: zookeeper
|
||||
timeout: 5s
|
||||
timeout: 3s
|
||||
# address: 121.229.45.214:9004
|
||||
address: 127.0.0.1:2181
|
||||
# address: 127.0.0.1:2181
|
||||
# address: 114.218.158.24:2181
|
||||
consumer:
|
||||
filter: tracing
|
||||
request-timeout: 300s
|
||||
references:
|
||||
OrderClientImpl:
|
||||
protocol: tri
|
||||
retries: 0
|
||||
interface: com.fontree.microservices.common.order # must be compatible with grpc or dubbo-java
|
||||
# filter: cshutdown,sign,fonDomainFilter,fonValidateFilter
|
||||
params:
|
||||
.accessKeyId: "SYD8-order-04"
|
||||
.secretAccessKey: "Al-order-FDF112"
|
||||
BundleClientImpl:
|
||||
protocol: tri
|
||||
retries: 0
|
||||
interface: com.fontree.microservices.fiee.bundle # must be compatible with grpc or dubbo-java
|
||||
AccountClientImpl:
|
||||
protocol: tri
|
||||
retries: 0
|
||||
@ -14,19 +31,62 @@ dubbo:
|
||||
params:
|
||||
.accessKeyId: "Accountksl"
|
||||
.secretAccessKey: "BSDY-FDF1-Fontree_account"
|
||||
|
||||
AccountFieeClientImpl:
|
||||
protocol: tri
|
||||
retries: 0
|
||||
retries: 3
|
||||
interface: com.fontree.microservices.common.micro.account.fiee
|
||||
# filter: cshutdown,sign,fonDomainFilter,fonValidateFilter
|
||||
# params:
|
||||
# .accessKeyId: "Accountksl"
|
||||
# .secretAccessKey: "BSDY-FDF1-Fontree_account"
|
||||
BundleClientImpl:
|
||||
# filter: echo,metrics,token,accesslog,sign,tps,generic_service,execute,pshutdown,auth,fonValidateFilter
|
||||
PaymentCentClientImpl:
|
||||
protocol: tri
|
||||
retries: 0
|
||||
interface: com.fontree.microservices.fiee.bundle # must be compatible with grpc or dubbo-java
|
||||
interface: com.fontree.microservices.common.payment.cent # must be compatible with grpc or dubbo-java
|
||||
CastClientImpl:
|
||||
protocol: tri
|
||||
interface: com.fontree.microservices.fiee.multicast
|
||||
interface: com.fontree.microservices.fiee.multicast
|
||||
SecFilingsClientImpl:
|
||||
protocol: tri
|
||||
retries: 0
|
||||
interface: com.fontree.microservices.fiee.SecFiling
|
||||
AyrshareClientImpl:
|
||||
protocol: tri
|
||||
interface: com.fontree.microservices.fiee.ayrshare
|
||||
logger:
|
||||
zap-config:
|
||||
level: error # 日志级别
|
||||
development: false
|
||||
disableCaller: false
|
||||
disableStacktrace: false
|
||||
encoding: "json"
|
||||
# zap encoder 配置
|
||||
encoderConfig:
|
||||
messageKey: "message"
|
||||
levelKey: "level"
|
||||
timeKey: "time"
|
||||
nameKey: "logger"
|
||||
callerKey: "caller"
|
||||
stacktraceKey: "stacktrace"
|
||||
lineEnding: ""
|
||||
levelEncoder: "capitalColor"
|
||||
timeEncoder: "iso8601"
|
||||
durationEncoder: "seconds"
|
||||
callerEncoder: "short"
|
||||
nameEncoder: ""
|
||||
EncodeTime: zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05.000"),
|
||||
EncodeDuration: zapcore.SecondsDurationEncoder,
|
||||
outputPaths:
|
||||
- "stderr"
|
||||
errorOutputPaths:
|
||||
- "stderr"
|
||||
lumberjack-config:
|
||||
# 写日志的文件名称
|
||||
filename: "runtime/logs/fiee.log"
|
||||
# 每个日志文件长度的最大大小,单位是 MiB。默认 100MiB
|
||||
maxSize: 5
|
||||
# 日志保留的最大天数(只保留最近多少天的日志)
|
||||
maxAge: 30
|
||||
# 只保留最近多少个日志文件,用于控制程序总日志的大小
|
||||
maxBackups: 30
|
||||
# 是否使用本地时间,默认使用 UTC 时间
|
||||
localTime: true
|
||||
# 是否压缩日志文件,压缩方法 gzip
|
||||
compress: false
|
||||
315
pkg/service/cast/ayrshare.go
Normal file
315
pkg/service/cast/ayrshare.go
Normal file
@ -0,0 +1,315 @@
|
||||
package cast
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"fonchain-fiee/pkg/utils"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const (
|
||||
// Ayrshare API 配置
|
||||
ayrshareAPIBaseURL = "https://api.ayrshare.com/api"
|
||||
maxSmallFileSize = 30 * 1024 * 1024 // 30MB
|
||||
apiKey = "208CBE9F-8E4F426A-990A0184-2C6287B9"
|
||||
)
|
||||
|
||||
// UploadMediaResponse 上传媒体文件响应
|
||||
type UploadMediaResponse struct {
|
||||
ID string `json:"id"`
|
||||
URL string `json:"url"`
|
||||
FileName string `json:"fileName"`
|
||||
Description string `json:"description"`
|
||||
IsAs bool `json:"isAs"`
|
||||
}
|
||||
|
||||
// UploadURLResponse 获取上传URL响应
|
||||
type UploadURLResponse struct {
|
||||
AccessURL string `json:"accessUrl"`
|
||||
ContentType string `json:"contentType"`
|
||||
UploadURL string `json:"uploadUrl"`
|
||||
}
|
||||
|
||||
// VerifyURLResponse 验证URL响应
|
||||
type VerifyURLResponse struct {
|
||||
Status string `json:"status"`
|
||||
StatusCode int `json:"statusCode"`
|
||||
ContentType string `json:"contentType"`
|
||||
}
|
||||
|
||||
// UploadMediaByURL 根据文件大小自动选择上传方式
|
||||
// fileURL: 文件的URL链接
|
||||
// apiKey: Ayrshare API Key
|
||||
// fileName: 文件名(可选)
|
||||
// description: 文件描述(可选)
|
||||
func UploadMediaByURL(ctx context.Context, fileURL, fileName, description string) (*UploadMediaResponse, error) {
|
||||
if fileURL == "" {
|
||||
return nil, errors.New("文件URL不能为空")
|
||||
}
|
||||
ok, err := VerifyMediaURL(ctx, fileURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ok {
|
||||
return &UploadMediaResponse{
|
||||
ID: "",
|
||||
URL: fileURL,
|
||||
FileName: "",
|
||||
Description: "",
|
||||
IsAs: false,
|
||||
}, nil
|
||||
}
|
||||
// 下载文件到临时目录
|
||||
tempFile, fileSize, err := downloadFile(ctx, fileURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("下载文件失败: %v", err)
|
||||
}
|
||||
defer os.Remove(tempFile) // 清理临时文件
|
||||
|
||||
zap.L().Info("文件下载完成", zap.String("tempFile", tempFile), zap.Int64("fileSize", fileSize))
|
||||
|
||||
// 如果没有提供文件名,从URL中提取
|
||||
if fileName == "" {
|
||||
fileName = filepath.Base(fileURL)
|
||||
}
|
||||
|
||||
// 根据文件大小选择上传方式
|
||||
if fileSize < maxSmallFileSize {
|
||||
zap.L().Info("使用小文件上传方式", zap.Int64("fileSize", fileSize))
|
||||
return uploadSmallMedia(ctx, tempFile, apiKey, fileName, description)
|
||||
}
|
||||
zap.L().Info("使用大文件上传方式", zap.Int64("fileSize", fileSize))
|
||||
return uploadLargeMedia(ctx, tempFile, apiKey, fileName, description)
|
||||
}
|
||||
|
||||
// downloadFile 下载文件到临时目录
|
||||
func downloadFile(ctx context.Context, fileURL string) (string, int64, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", fileURL, nil)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Minute}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", 0, fmt.Errorf("下载文件失败,HTTP状态码: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// 创建临时文件
|
||||
tempFile, err := os.CreateTemp("", "ayrshare_upload_*")
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
defer tempFile.Close()
|
||||
|
||||
// 复制内容到临时文件
|
||||
fileSize, err := io.Copy(tempFile, resp.Body)
|
||||
if err != nil {
|
||||
os.Remove(tempFile.Name())
|
||||
return "", 0, err
|
||||
}
|
||||
|
||||
return tempFile.Name(), fileSize, nil
|
||||
}
|
||||
|
||||
// uploadSmallMedia 上传小于30MB的文件(使用multipart form-data)
|
||||
func uploadSmallMedia(ctx context.Context, filePath, apiKey, fileName, description string) (*UploadMediaResponse, error) {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("打开文件失败: %v", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// 创建multipart form-data
|
||||
body := &bytes.Buffer{}
|
||||
writer := multipart.NewWriter(body)
|
||||
|
||||
// 添加文件
|
||||
part, err := writer.CreateFormFile("file", fileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := io.Copy(part, file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 添加其他字段
|
||||
if fileName != "" {
|
||||
_ = writer.WriteField("fileName", fileName)
|
||||
}
|
||||
if description != "" {
|
||||
_ = writer.WriteField("description", description)
|
||||
}
|
||||
|
||||
if err := writer.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 发送请求
|
||||
url := fmt.Sprintf("%s/media/upload", ayrshareAPIBaseURL)
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", url, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", apiKey))
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Minute}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("请求失败: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("读取响应失败: %v", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
zap.L().Error("上传小文件失败", zap.Int("statusCode", resp.StatusCode), zap.String("response", string(respBody)))
|
||||
return nil, fmt.Errorf("上传失败: HTTP %d, %s", resp.StatusCode, string(respBody))
|
||||
}
|
||||
|
||||
var result UploadMediaResponse
|
||||
if err := json.Unmarshal(respBody, &result); err != nil {
|
||||
return nil, fmt.Errorf("解析响应失败: %v", err)
|
||||
}
|
||||
|
||||
zap.L().Info("小文件上传成功", zap.Any("response", result))
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// uploadLargeMedia 上传大于30MB的文件(使用presigned URL)
|
||||
func uploadLargeMedia(ctx context.Context, filePath, apiKey, fileName, description string) (*UploadMediaResponse, error) {
|
||||
// 获取文件的content type
|
||||
ext := filepath.Ext(fileName)
|
||||
if len(ext) > 0 {
|
||||
ext = ext[1:] // 去掉点号
|
||||
}
|
||||
|
||||
// Step 1: 获取上传URL
|
||||
uploadURLResp, err := getUploadURL(ctx, apiKey, fileName, ext)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取上传URL失败: %v", err)
|
||||
}
|
||||
|
||||
zap.L().Info("获取上传URL成功", zap.Any("uploadURLResp", uploadURLResp))
|
||||
|
||||
// Step 2: 上传文件到presigned URL
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("打开文件失败: %v", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "PUT", uploadURLResp.UploadURL, file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", uploadURLResp.ContentType)
|
||||
|
||||
client := &http.Client{Timeout: 30 * time.Minute}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("上传文件失败: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
respBody, _ := io.ReadAll(resp.Body)
|
||||
zap.L().Error("上传大文件失败", zap.Int("statusCode", resp.StatusCode), zap.String("response", string(respBody)))
|
||||
return nil, fmt.Errorf("上传失败: HTTP %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
zap.L().Info("大文件上传成功")
|
||||
|
||||
// 返回结果
|
||||
return &UploadMediaResponse{
|
||||
URL: uploadURLResp.AccessURL,
|
||||
FileName: fileName,
|
||||
Description: description,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// getUploadURL 获取大文件上传的presigned URL
|
||||
func getUploadURL(ctx context.Context, apiKey, fileName, contentType string) (*UploadURLResponse, error) {
|
||||
url := fmt.Sprintf("%s/media/uploadUrl?fileName=%s", ayrshareAPIBaseURL, fileName)
|
||||
if contentType != "" {
|
||||
url = fmt.Sprintf("%s&contentType=%s", url, contentType)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", apiKey))
|
||||
|
||||
client := &http.Client{Timeout: 30 * time.Second}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
zap.L().Error("获取上传URL失败", zap.Int("statusCode", resp.StatusCode), zap.String("response", string(respBody)))
|
||||
return nil, fmt.Errorf("获取上传URL失败: HTTP %d, %s", resp.StatusCode, string(respBody))
|
||||
}
|
||||
|
||||
var result UploadURLResponse
|
||||
if err := json.Unmarshal(respBody, &result); err != nil {
|
||||
return nil, fmt.Errorf("解析响应失败: %v", err)
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// VerifyMediaURL 验证媒体URL是否有效
|
||||
func VerifyMediaURL(ctx context.Context, mediaURL string) (bool, error) {
|
||||
url := fmt.Sprintf("%s/media/urlExists", ayrshareAPIBaseURL)
|
||||
requestBody := map[string]string{
|
||||
"mediaUrl": mediaURL,
|
||||
}
|
||||
jsonData, _ := json.Marshal(requestBody)
|
||||
code, postBody, err := utils.PostBytesHeader(url, map[string]interface{}{
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer " + apiKey,
|
||||
}, jsonData)
|
||||
if err != nil {
|
||||
zap.L().Error("VerifyMediaURL 提交异常", zap.Error(err))
|
||||
return false, errors.New("验证链接提交异常")
|
||||
}
|
||||
if code != http.StatusOK {
|
||||
return false, nil
|
||||
}
|
||||
var result *VerifyURLResponse
|
||||
_ = json.Unmarshal(postBody, &result)
|
||||
if result.StatusCode != http.StatusOK || result.Status != "success" {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
@ -99,6 +99,26 @@ func Test(ctx *gin.Context) {
|
||||
service.Success(ctx, resp)
|
||||
return
|
||||
}
|
||||
if action == "upload" {
|
||||
fileUrl := ctx.PostForm("fileUrl")
|
||||
uploadResp, err := UploadMediaByURL(ctx, fileUrl, "", "")
|
||||
if err != nil {
|
||||
service.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
service.Success(ctx, uploadResp)
|
||||
return
|
||||
}
|
||||
if action == "getUrl" {
|
||||
fileUrl := ctx.PostForm("fileUrl")
|
||||
uploadResp, err := VerifyMediaURL(ctx, fileUrl)
|
||||
if err != nil {
|
||||
service.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
service.Success(ctx, uploadResp)
|
||||
return
|
||||
}
|
||||
service.Success(ctx, "unknow")
|
||||
return
|
||||
}
|
||||
|
||||
@ -453,11 +453,37 @@ func PostAS(workUuids []string) (errs []error) {
|
||||
var isVideo bool
|
||||
if workDetail.WorkCategory == 1 {
|
||||
isVideo = false
|
||||
mediaUrls = workDetail.Images
|
||||
for _, imageUrl := range workDetail.Images {
|
||||
urlResp, err := UploadMediaByURL(context.Background(), imageUrl, "", "")
|
||||
if err != nil {
|
||||
zap.L().Error("Publish UploadMediaByURL failed", zap.String("imageUrl", imageUrl), zap.Error(err))
|
||||
continue
|
||||
}
|
||||
mediaUrls = append(mediaUrls, urlResp.URL)
|
||||
}
|
||||
//mediaUrls = workDetail.Images
|
||||
}
|
||||
var coverUrl string
|
||||
if workDetail.WorkCategory == 2 {
|
||||
isVideo = true
|
||||
mediaUrls = []string{workDetail.VideoUrl}
|
||||
//mediaUrls = []string{workDetail.VideoUrl}
|
||||
urlResp, err := UploadMediaByURL(context.Background(), workDetail.VideoUrl, "", "")
|
||||
if err != nil {
|
||||
zap.L().Error("Publish UploadMediaByURL failed", zap.String("VideoUrl", workDetail.VideoUrl), zap.Error(err))
|
||||
continue
|
||||
}
|
||||
mediaUrls = []string{urlResp.URL}
|
||||
if workDetail.CoverUrl != "" {
|
||||
urlResp, err = UploadMediaByURL(context.Background(), workDetail.VideoUrl, "", "")
|
||||
if err != nil {
|
||||
zap.L().Error("Publish UploadMediaByURL failed", zap.String("VideoUrl", workDetail.VideoUrl), zap.Error(err))
|
||||
continue
|
||||
}
|
||||
coverUrl = urlResp.URL
|
||||
}
|
||||
}
|
||||
if len(mediaUrls) == 0 {
|
||||
continue
|
||||
}
|
||||
ArtistInfoResp, _err := service.CastProvider.GetArtist(context.Background(), &cast.GetArtistReq{
|
||||
ArtistUuid: workDetail.ArtistUuid,
|
||||
@ -470,7 +496,6 @@ func PostAS(workUuids []string) (errs []error) {
|
||||
errs = append(errs, errors.New("艺人平台信息未配置"))
|
||||
continue
|
||||
}
|
||||
|
||||
for _, platformID := range needPlatformIDs {
|
||||
var postResp *aryshare.PostResponse = &aryshare.PostResponse{}
|
||||
postReq := &aryshare.PostRequest{
|
||||
@ -489,7 +514,7 @@ func PostAS(workUuids []string) (errs []error) {
|
||||
postReq.InstagramOptions = &aryshare.InstagramOptions{
|
||||
ShareReelsFeed: false,
|
||||
AudioName: "",
|
||||
ThumbNail: workDetail.CoverUrl,
|
||||
ThumbNail: coverUrl,
|
||||
ThumbNailOffset: 0,
|
||||
Stories: false,
|
||||
AltText: nil,
|
||||
|
||||
44
pkg/utils/files.go
Normal file
44
pkg/utils/files.go
Normal file
@ -0,0 +1,44 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"fonchain-fiee/pkg/e"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// SaveUrlFileDisk 保存图片到本地
|
||||
func SaveUrlFileDisk(url string, path string, filename string) (fullPath string, err error) {
|
||||
if err = CreateDirPath(path); err != nil {
|
||||
zap.L().Error("SaveUrlFileDisk err ", zap.Error(err))
|
||||
return
|
||||
}
|
||||
if filename == "" {
|
||||
stepName := strings.Split(url, "/")
|
||||
if len(stepName) > 1 {
|
||||
filename = stepName[len(stepName)-1]
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
err = errors.New(e.GetMsg(e.ERROR_DOWNLOAD_FILE))
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
|
||||
}
|
||||
resp.Body.Close()
|
||||
}()
|
||||
bytes, err := io.ReadAll(resp.Body)
|
||||
fullPath = fmt.Sprintf("%s/%s", path, filename)
|
||||
// 写入数据
|
||||
err = os.WriteFile(fullPath, bytes, 0777)
|
||||
return
|
||||
}
|
||||
@ -133,3 +133,24 @@ func GetUrl(apiUrl string, headerData map[string]string, proxyURL ...string) (st
|
||||
zap.L().Info("Get", zap.Any("url", apiUrl), zap.Any("body", body))
|
||||
return
|
||||
}
|
||||
|
||||
func PostBytesHeader(url string, header map[string]interface{}, data []byte) (int, []byte, error) {
|
||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return 0, nil, fmt.Errorf("创建请求失败: %v", "")
|
||||
}
|
||||
for k, v := range header {
|
||||
req.Header.Set(k, fmt.Sprintf("%v", v))
|
||||
}
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return 0, nil, fmt.Errorf("请求失败: %v", "")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return 0, nil, fmt.Errorf("读取响应失败: %v", "")
|
||||
}
|
||||
return resp.StatusCode, body, nil
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
@ -163,3 +164,11 @@ func CopyFile(src, dstDir string) (string, error) {
|
||||
}
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
func FileNameFromURL(rawURL string) (string, error) {
|
||||
u, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return path.Base(u.Path), nil
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user